﻿using System;
using UnityEngine;

public interface IIndexString
{
    string this[int index] { get; }
}

namespace GCommon
{
    public interface IGetId
    {
        uint GetId();
    }

    public abstract class CsvDataIndexedReading: CSVBaseData
    {
        public override void ParseData(long index, int fieldCount, string[] headers, string[] values)
        {
            Debug.Assert(false, "ParseData() got called " + GetType());
        }

        public override bool UsingIndexedParseData
        {
            get { return true; }
        }
        public override string[] GetHeadColNames()
        {
            Debug.Assert(false, "GetHeadColNames() got called " + GetType());
            return null;
        }

        public override void ParseData(IIndexString ss, int[] index)
        {
            Debug.Assert(false, "ParseData(index) got called " + GetType());
        }

    }
    
    public abstract class CSVBaseData
    {
        public abstract void ParseData(long index, int fieldCount, string[] headers, string[] values);
        public abstract string GetPrimaryKey();
        public T As<T>() where T : CSVBaseData
        {
            return (T)this;
        }
        
        public virtual bool UsingIndexedParseData
        {
            get { return false; }
        }

        public virtual string[] GetHeadColNames()
        {
            return null;
        }

        public virtual void ParseData(IIndexString ss, int[] index)
        {
            
        }

        protected static float ReadFloat(string fieldName, string[] headers, string[] values, float defaultValue = 0f)
        {
            string value = GetFieldValueWithFieldName(fieldName, headers, values);
            return StringConverter.ToFloat(value, defaultValue);
        }
        protected static int ReadInt(string fieldName, string[] headers, string[] values, int defaultValue = 0)
        {
            string value = GetFieldValueWithFieldName(fieldName, headers, values);
            return StringConverter.ToInt(value, defaultValue);
        }

        protected static int ReadInt(string value,int defaultValue = 0)
        {
            return StringConverter.ToInt(value, defaultValue);
        }
        protected static uint ReadUInt(string fieldName, string[] headers, string[] values, uint defaultValue = 0)
        {
            string value = GetFieldValueWithFieldName(fieldName, headers, values);
            return ReadUInt(value, defaultValue);
        }

        protected static uint ReadUInt(string value, uint defaultValue)
        {
            return StringConverter.ToUInt(value, defaultValue);
        }
        protected static uint ReadUInt(string value)
        {
            uint t = 0, b = 1;
            if (value != null)
            {
                for (var i = value.Length - 1; i >= 0; i--)
                {
                    var c = value[i];
                    if (c == ' ')
                        continue;
                    t += (uint)(c -'0') * b;
                    b *= 10;
                }
            }
            return t;
        }

        protected static string ReadString(string fieldName, string[] headers, string[] values, string defaultValue = null)
        {
            return GetFieldValueWithFieldName(fieldName, headers, values);
        }

        protected static string[] ReadStringArray(string fieldName, string[] headers, string[] values, string defaultValue = null)
        {
            string value = GetFieldValueWithFieldName(fieldName, headers, values);
            if (value == null)
                return null;
            string[] result = value.Split(',');
            return result;
        }
        protected static uint[] ReadUIntArray(string fieldName, string[] headers, string[] values, uint defaultValue = 0, char InSplitChar = ',')
        {
            string value = GetFieldValueWithFieldName(fieldName, headers, values);
            string[] strResult = value.Split(InSplitChar);
            uint[] result = new uint[strResult.Length];
            for(int i =0; i<strResult.Length; i++)
            {
                result[i] = StringConverter.ToUInt(strResult[i]);
            }
            return result;
        }

        protected static int[] ReadIntArray(string fieldName, string[] headers, string[] values, uint defaultValue = 0, char InSplitChar = ',')
        {
            string value = GetFieldValueWithFieldName(fieldName, headers, values);
            string[] strResult = value.Split(InSplitChar);
            int[] result = new int[strResult.Length];
            for (int i = 0; i < strResult.Length; i++)
            {
                result[i] = StringConverter.ToInt(strResult[i]);
            }
            return result;
        }

        protected static float[] ReadFloatArray(string fieldName, string[] headers, string[] values, char InSplitChar = '#')
        {
            string value = GetFieldValueWithFieldName(fieldName, headers, values);
            string[] strResult = value.Split(InSplitChar);
            float[] result = new float[strResult.Length];
            for(int i =0; i<strResult.Length; i++)
            {
                result[i] = StringConverter.ToFloat(strResult[i]);
            }
            return result;
        }
        protected static bool ReadBoolean(string fieldName, string[] headers, string[] values, bool defaultValue = false)
        {
            string value = GetFieldValueWithFieldName(fieldName, headers, values);
            return ReadBoolean(value);
        }

        protected static bool ReadBoolean(string value)
        {
            //var t =  StringConverter.ToBool(value, defaultValue);
            var t = value != null && value.Length == 4;
            if (t)
            {
                var c = value[0];
                t &= c == 'T' || c == 't';
                c = value[1];
                t &= c == 'R' || c == 'r';
                c = value[2];
                t &= c == 'U' || c == 'u';
                c = value[3];
                t &= c == 'E' || c == 'e';
            }
            return t;
        }

        protected static ResourceID ReadResourceID(string fieldName, string[] headers, string[] values, Type resVarType)
        {
            //string strResID = ReadString(fieldName, headers, values);
            //if (!string.IsNullOrEmpty(strResID))
            //    return ResourceManager.instance.GetResourceIDByName(resVarType, strResID, false);

            return ResourceID.INVALID;
        }

        protected static ResourceID ReadResourceID(string strResID, Type resVarType)
        {
            //if (!string.IsNullOrEmpty(strResID))
            //    return ResourceManager.instance.GetResourceIDByName(resVarType, strResID, false);
            return ResourceID.INVALID;
        }

        protected static ResourceID[] ReadResourceIDArray(string fieldName, string[] headers, string[] values, Type resVarType)
        {
            string[] stringArray = ReadStringArray(fieldName, headers, values);
            if (stringArray == null)
                return null;
            ResourceID[] resourceIDArray = new ResourceID[stringArray.Length];
            string strResID;
            for (int i = 0; i < stringArray.Length; i++)
            {
                strResID = stringArray[i];
                if (!string.IsNullOrEmpty(strResID))
                {
                    //resourceIDArray[i] = ResourceManager.instance.GetResourceIDByName(resVarType, strResID, false);
                }
                else
                {
                    resourceIDArray[i] = ResourceID.INVALID;
                }
            }
            return resourceIDArray;
        }

        protected static string GetFieldValueWithFieldName(string fieldName, string[] headers, string[] values)
        {
            string result = null;
            int index = -1;
            if (headers != null && headers.Length > 0 && !string.IsNullOrEmpty(fieldName))
            {
                for (int i = 0, count = headers.Length; i < count; i++)
                {
                    string head = headers[i];
                    if (string.Equals(fieldName, head))
                    {
                        index = i;
                        break;
                    }
                }
                if (index >= 0 && index < values.Length)
                {
                    result = values[index];
                }
            }
            return result;
        }
        

        public static implicit operator bool(CSVBaseData exists)
        {
            return exists != null;
        }

    }
}
